Data in a relational database are typically organized in logical, row-column storage structures called tables. The data stored within each row of a table collectively form a storage record (“record” for short) with the columns of the table defining respective storage fields within the records. Thus, tables may be viewed as arrays of records, with each record being a multi-field data structure. Referring to the simple prior art table shown in FIG. 1, for example, the table designated ‘Table1’ is a two-deep array of records in which each record includes an employee number field and an employee name field.
Most modern database management systems (DBMS) provide a structured query language (SQL) interface to allow users to define, access and manipulate data within the DBMS. For example, a typical SQL interface may be used to define Table1 as follows (‘number’ and ‘varchar2’ are primitive types for numeric and character data, respectively):
SQL> create table Table1 ( EmpNo number, EmpName varchar2(30));                Table created.        
SQL> insert into Table1 values (123, ‘Johnson’);                1 row created.        
SQL> insert into Table1 values (124, ‘Scott’);                1 row created.        
As Table1 has been created and populated with two records, the SQL interface may now be used to query Table1 as follows:
SQL> select * from Table1;EmpNoEmpName123Johnson124Scott
Some modem database systems permit definition and execution of specialized functions called table functions which return collections of data much like a table query operation. As a simple example, a table function that returns static data corresponding to the query result above may be defined using the SQL interface as follows:
SQL> create type employee_t as object ( EmpNo number, EmpName varchar2(30));                Type created.        
SQL> create type employee_coll as table of employee_t;                Type created        
SQL> create function Tfx(DataSource varchar2) return employee_coll is
2 begin
3 return employee_coll (employee_t (123, ‘Johnson’), employee_t (124 ‘Scott’));
4 end;                Function created.        
The SQL interface may now be used to execute table function Tfx as follows
SQL> select * from table (Tfx(‘ ’));EmpNoEmpName123Johnson124ScottNote that in this simple example, the function argument ‘DataSource’ is not referenced within the body of the table function so that the value of the input parameter (a space in this example) does not affect the function output.
FIG. 2 illustrates the definition, compilation and execution of a table function in a prior-art DBMS. Herein the term function is used to mean a sequence of instructions that may be executed by a processor and includes, without limitation, procedures, methods, subroutines and other expressions describing such sequences of instructions. At block 101 of the definition phase, a database application developer (i.e., one who develops database applications typically using various programming interfaces and tools provided in a commercially available DBMS) creates an element type and collection type and registers the types with the DBMS. The element type defines the fields within individual records returned by the table function, and the collection type is an array of element types. Referring to the table function, Tfx, defined above, for example, the SQL interface is used to create an element type, employee_t, that defines the fields (EmpNo and EmpName) within each record returned by the table function, and a collection type, employee_coll, that defines an array of employee_t data elements. At block 103 of the definition phase, the application developer creates a table function declared to return the collection type. In block 105 of the compilation phase, an application user issues a query referencing the table function. In the example shown above and in block 105, the wildcard operator ‘*’ is used to select all fields of the element type to be returned by the table function. Also, as shown in block 105, the argument list of the table function may include one or more arguments (i.e., arg1, arg2, . . . ). At block 107 of the compilation phase, the DBMS processes the query, including type-checking the query using the return type declared for the table function. By this operation, the DBMS ensures that the data returned by the table function will be in a pre-defined format that can be returned to the user, avoiding type inconsistencies and other errors that often generate exceptions and errors in data processing systems. At block 109, the execution phase of the query is begun when the DBMS calls the table function, providing the arguments supplied by the user in block 105. The table function is executed in block 111 and returns the query result to the DBMS in the format of the type declared in the definition phase (i.e., at block 103). The DBMS, in turn, returns the type-formatted query result to the user at block 113, concluding the query execution.
Reflecting on the query definition, compilation and execution phases illustrated in FIG. 2 and the example above, it should be noted that table functions are often used to fetch and process information from remote data sources or external data sources which have a proprietary non-SQL query interface, such as databases accessible over computer networks (e.g., the world-wide packet data communication network now commonly referred to as the Internet or similar, private packet data communication networks sometimes referred to as intranets). Thus, while a simple example having a static data definition is set forth above, the actual organization and type of data stored in the remote data source may vary from data source to data source. One approach to accommodating such varying data source organizations is to create different data types (element types and collection types) and table functions according to the nature of the different data sources from which data is to be fetched. As there may be hundreds, thousands or more of such data sources, each to be processed in a similar manner (e.g., return all data) but having different organizations and/or data types, creating dedicated data types and functions for each data source is often impractical. Worse, in many cases the organization and type of data stored in the remote data source may not be known in advance (e.g., as in a database application programmed to seek out data sources over the Internet and return contents according to user-specified selection criteria) so that advance creation of dedicated data types and functions is not feasible. Another solution to handling a wide variety of data source organizations and data types is to define an opaque container type that can store any type of query result. One example of such an opaque container type is a binary large object (“blob”), which may be used to store an aggregation of multiple component values of a record. That is, all the component fields within a given record are combined in non-delimited form within a blob, with the table function being declared to return a collection of blobs. While the opaque container solution generally allows for retrieval of data in numerous organizations and types, the aggregation of component values within a blob represents a loss of information that the DBMS generally cannot recover. That is, the DBMS typically cannot unpack the blob into row-column format as no information about the formatting of fields within the blob is provided. Consequently, the user (or application developer) is typically left to convert the array of blobs into a readable format (i.e., assuming that conversion information is available), a generally inefficient and inconvenient operation for most users.